﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <vector>
using namespace std;
// 原题连接：https://leetcode.cn/problems/binary-tree-coloring-game/description/
/*
题目描述：
有两位极客玩家参与了一场「二叉树着色」的游戏。游戏中，给出二叉树的根节点 root，树上总共有 n 个节点，且 n 为奇数，其中每个节点上的值从 1 到 n 各不相同。

最开始时：

「一号」玩家从 [1, n] 中取一个值 x（1 <= x <= n）；
「二号」玩家也从 [1, n] 中取一个值 y（1 <= y <= n）且 y != x。
「一号」玩家给值为 x 的节点染上红色，而「二号」玩家给值为 y 的节点染上蓝色。

之后两位玩家轮流进行操作，「一号」玩家先手。每一回合，玩家选择一个被他染过色的节点，将所选节点一个 未着色 的邻节点（即左右子节点、或父节点）进行染色（「一号」玩家染红色，「二号」玩家染蓝色）。

如果（且仅在此种情况下）当前玩家无法找到这样的节点来染色时，其回合就会被跳过。

若两个玩家都没有可以染色的节点时，游戏结束。着色节点最多的那位玩家获得胜利 ✌️。

现在，假设你是「二号」玩家，根据所给出的输入，假如存在一个 y 值可以确保你赢得这场游戏，则返回 true ；若无法获胜，就请返回 false 。


示例 1 ：


输入：root = [1,2,3,4,5,6,7,8,9,10,11], n = 11, x = 3
输出：true
解释：第二个玩家可以选择值为 2 的节点。
示例 2 ：

输入：root = [1,2,3], n = 3, x = 1
输出：false


提示：

树中节点数目为 n
1 <= x <= n <= 100
n 是奇数
1 <= Node.val <= n
树中所有值 互不相同
*/


struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

 // 开始解题：
 // 方法——dfs
class Solution {
public:
    // 根据题目描述，则我们最后染色完后，蓝色褐红色的曲艺定义两片联通块
    // 既然是联通块，则我们在游戏开始后，第一个选择要染成蓝色的点就只能有三种情况：
    // 红色节点的父节点或左孩子或右孩子
    int get_count(TreeNode* root) {
        // 计算以root为根的树的总结点个数
        if (nullptr == root) {
            return 0;
        }
        return get_count(root->left) + get_count(root->right) + 1;
    }
    TreeNode* left = nullptr;
    TreeNode* right = nullptr;
    int x = 0;
    bool preorder(TreeNode* root) {
        if (nullptr == root) {
            return false;
        }
        if (root->val == x) {
            left = root->left;
            right = root->right;
            return true;
        }
        if (preorder(root->left)) {
            return true;
        }
        if (preorder(root->right)) {
            return true;
        }
        return false;
    }

    bool btreeGameWinningMove(TreeNode* root, int n, int _x) {
        x = _x;
        preorder(root);
        int total = get_count(root); // 整棵树的节点个数
        int left_count = get_count(left);
        int right_count = get_count(right);
        if (left) {
            // 选择左孩子
            if (left_count > total - left_count) {
                return true;
            }
        }
        if (right) {
            // 选择右孩子
            if (right_count > total - right_count) {
                return true;
            }
        }
        // 选择父节点
        int red_count = left_count + right_count + 1;
        return total - red_count > red_count;
    }
};